import {ReactNode, useMemo, useState} from "react";
import {Stage} from "@pixi/react";

import './CameraView.css'
import {CameraViewContext} from "./CameraViewContext.ts";
import {useWindowSize} from "react-use";


/**
 * 整个场景宽度是 sceneWidth，左上角是原点 (0,0)
 * 相机的镜头宽度由屏幕大小决定，相机镜头在整个场景中移动
 */
export interface CameraViewProps {

    // 场景的总大小
    sceneWidth: number;

    // 子组件
    children: ReactNode;
}

export function AppCameraView(cameraViewProps: CameraViewProps) {

    // 监听屏幕尺寸变化重新渲染琴键
    const {width, height} = useWindowSize();

    // 相机左侧 与 原点 （琴键A0的左侧） 的距离
    const [cameraOffsetX, setCameraOffsetX] = useState<number>(0);

    // 镜头可以移动的最大偏移量
    const maxCameraOffsetX = useMemo(() => {
        const deltaX = cameraViewProps.sceneWidth - width;

        // 如果场景比镜头的视野还小，则镜头没法移动
        return deltaX > 0 ? deltaX : 0;

    }, [cameraViewProps.sceneWidth, width]);

    // 记录是不是在拖动镜头
    const [isDragging, setIsDragging] = useState<boolean>(false);

    // 记录鼠标移动时的位置，只有在拖动镜头时才有用
    const [currentMouseX, setCurrentMouseX] = useState<number>(0);


    const mouseDown = (clientX: number) => {
        setIsDragging(true);
        setCurrentMouseX(clientX);
    }

    const mouseUp = () => {
        setIsDragging(false);
    }

    const mouseMove = (clientX: number) => {
        // 防止镜头超出场景，所以要限制镜头移动范围
        // 只有在场景范围内才允许拖动
        if (isDragging && cameraOffsetX >= 0 && cameraOffsetX <= maxCameraOffsetX) {
            // 如果 movePixels>0, 则为鼠标往右拖动，意味着希望看到左侧区域
            const movePixels = clientX - currentMouseX;

            setCameraOffsetX(value => {
                let offset = value - movePixels;

                if (offset < 0) {
                    // offset 的最小是0，否则左边会有空白
                    offset = 0;
                } else if (offset > maxCameraOffsetX) {
                    // left 的最大值是 maxDisplayOffset，否则右边会有空白
                    offset = maxCameraOffsetX;
                }

                return offset;
            });
            setCurrentMouseX(clientX);
        }
    }

    return <div
        className="camera-view-container"
        onMouseDown={(e) => mouseDown(e.clientX)}
        onMouseUp={() => mouseUp()}
        onMouseMove={(e) => mouseMove(e.clientX)}
        onTouchStart={(e) => e.touches[0] && mouseDown(e.touches[0].clientX)}
        onTouchEnd={() => mouseUp()}
        onTouchMove={(e) => e.touches[0] && mouseMove(e.touches[0].clientX)}>

        {/*我也不知道为什么，但是CameraViewContext.Provider 放在 Stage 外面，他的context就传不进去*/}
        <Stage
            width={width}
            height={height}
            options={{background: "#0D141E"}}>
            <CameraViewContext.Provider value={
                {
                    cameraViewOffsetX: cameraOffsetX,
                    cameraViewWidth: width,
                    cameraViewHeight: height,
                    sceneWidth: cameraViewProps.sceneWidth,
                    sceneHeight: height
                }
            }>
                {cameraViewProps.children}
            </CameraViewContext.Provider>
        </Stage>
    </div>

}